home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / t3_1 / risc_src.lha / risc_sources / comp / back_end / bookkeep.t < prev    next >
Encoding:
Text File  |  1989-10-27  |  16.3 KB  |  506 lines

  1. (herald (back_end bookkeep)
  2.   (env t (orbit_top defs)))
  3.  
  4. ;;; Copyright (c) 1985 Yale University
  5. ;;;     Authors: N Adams, R Kelsey, D Kranz, J Philbin, J Rees.
  6. ;;; This material was developed by the T Project at the Yale University Computer 
  7. ;;; Science Department.  Permission to copy this software, to redistribute it, 
  8. ;;; and to use it for any purpose is granted, subject to the following restric-
  9. ;;; tions and understandings.
  10. ;;; 1. Any copy made of this software must include this copyright notice in full.
  11. ;;; 2. Users of this software agree to make their best efforts (a) to return
  12. ;;;    to the T Project at Yale any improvements or extensions that they make,
  13. ;;;    so that these may be included in future releases; and (b) to inform
  14. ;;;    the T Project of noteworthy uses of this software.
  15. ;;; 3. All materials developed as a consequence of the use of this software
  16. ;;;    shall duly acknowledge such use, in accordance with the usual standards
  17. ;;;    of acknowledging credit in academic research.
  18. ;;; 4. Yale has made no warrantee or representation that the operation of
  19. ;;;    this software will be error-free, and Yale is under no obligation to
  20. ;;;    provide any services, by way of maintenance, update, or otherwise.
  21. ;;; 5. In conjunction with products arising from the use of this material,
  22. ;;;    there shall be no use of the name of the Yale University nor of any
  23. ;;;    adaptation thereof in any advertising, promotional, or sales literature
  24. ;;;    without prior written consent from Yale in each case.
  25. ;;;
  26.  
  27. ;;; Copyright (c) 1985 David Kranz
  28.  
  29. (define (do-reg-positions node args p-list proc?)
  30.   (if p-list
  31.       (return args p-list)
  32.       (let ((len (length args))
  33.         (m (if proc? (fx+ *argument-registers* 1) *argument-registers*)))
  34.     (cond ((fx<= len m)
  35.            (return args (reg-positions len proc?)))
  36.           (else
  37.            (generate-extra-args-cons (fx- len m))
  38.            (do ((a (nthcdr args m) (cdr a))
  39.             (i 0 (fx+ i 1)))
  40.            ((null? a) (return (sublist args 0 m)
  41.                       (reg-positions m proc?)))
  42.          (generate-extra-arg-store node (car a) i)))))))
  43.  
  44. (define (reg-positions i proc?)
  45.   (let ((end (if proc? i (fx+ i 1))))
  46.     (do ((i (if proc? p (fx+ p 1)) (fx+ i 1))
  47.      (l '() (cons (if (fx<= i *argument-registers*)
  48.               i
  49.               (bug "Too many arguments"))
  50.               l)))
  51.     ((fx>= i end)
  52.      (reverse! l)))))
  53.  
  54. (define-constant lambda-max-temps node-instructions)
  55. (define-constant lambda-known-state node-instructions)
  56.  
  57. ;;; Registers and temps are represented in the same structure
  58.  
  59. (define-integrable reg-node
  60.   (object (lambda (reg) 
  61.             (vref *registers* reg))
  62.           ((setter self) 
  63.            (lambda (reg node)
  64.              (vset *registers* reg node)))))
  65.                          
  66. (define-integrable temp-node reg-node)
  67.  
  68. ;;; ->REGISTER Move the value of leaf-node REF into a register of type TYPE
  69. ;;; which can be either '* or a specific register. Force an existing value out
  70. ;;; if necessary,
  71.  
  72. (define (access-value node var)
  73.   (->addressable node var))
  74.  
  75. (define (->addressable node var)
  76.   (let ((acc (lookup-value node var)))
  77.     (cond ((allowed-mode? acc)
  78.        acc)
  79.       (else
  80.        (into-register node var acc)))))
  81.  
  82.  
  83. (define (->register node var)
  84.   (let ((accessor (lookup-value node var)))
  85.     (cond ((register? accessor)
  86.            accessor)
  87.           (else 
  88.            (into-register node var accessor)))))
  89.  
  90. (define (allocated-register? x)
  91.   (and (register? x) (fx>= x 0)))
  92.  
  93. (define (get-target-register node cont reg1 reg2)
  94.   (receive (reg call) (continuation-wants cont)
  95.     (let ((call (and call (call-hoisted-cont call))))
  96.       (cond ((and call (neq? (call-hoisted-cont node) call))
  97.          (get-stack-register node))
  98.         ((not (register? reg))
  99.          (cond ((and (allocated-register? reg1)
  100.              (dying? (reg-node reg1) node))
  101.             (kill (reg-node reg1))
  102.             reg1)
  103.                ((and (allocated-register? reg2)
  104.              (dying? (reg-node reg2) node))
  105.             (kill (reg-node reg2))
  106.             reg2)
  107.            (else
  108.             (get-register node))))
  109.         (else
  110.          (let ((var (reg-node reg)))
  111.            (cond ((not var) reg)
  112.              ((not (variable? var))
  113.               (get-register node))
  114.              ((and (eq? reg reg1) (dying? var node))
  115.               (kill var)
  116.               reg1)
  117.              ((and (eq? reg reg2) (dying? var node))
  118.               (kill var)
  119.               reg2)
  120.              ((leaf-node? cont)
  121.               (kill var)
  122.               reg)
  123.              (else
  124.               (iterate loop ((var var) (regs (list reg)))
  125.                       (receive (reg cnode) (likely-next-reg-1 var cont)
  126.              (let ((after-call?
  127.                 (and call cnode
  128.                      (neq? (call-hoisted-cont cnode) call))))
  129.               (cond ((or (null? reg) after-call?)
  130.                  (cond ((and (not after-call?)
  131.                          (get-reg-if-free node))
  132.                     => (lambda (reg)
  133.                          (move-registers reg regs)))
  134.                        ((temp-loc var)
  135.                     (set (register-loc var) nil)
  136.                     (move-registers (car regs) (cdr regs)))
  137.                        (else
  138.                     (move-registers (get-stack-slot node)
  139.                             regs))))
  140.                 ((or (eq? reg reg1) (eq? reg reg2))
  141.                  (get-register node))
  142.                 ((reg-node reg)
  143.                  => (lambda (var)
  144.                       (cond ((or (not (variable? var))
  145.                          (memq? reg regs))
  146.                          (get-register node))
  147.                         (else
  148.                          (loop var (cons reg regs))))))
  149.                 (else
  150.                  (move-registers reg regs))))))))))))))
  151.  
  152.  
  153. (define (move-registers last regs)
  154.   (iterate loop ((to last) (regs regs))
  155.     (cond ((null? regs) to)
  156.       (else
  157.        (let* ((from (car regs))
  158.           (from-var (reg-node from)))
  159.          (set (register-loc from-var) nil)
  160.          (set (temp-loc from-var) nil)
  161.          (mark from-var to)
  162.          (generate-move from to)
  163.          (loop from (cdr regs)))))))
  164.          
  165.  
  166.  
  167. (lset get-register (lambda (node)
  168.              (really-get-register node P *real-registers* t)))
  169.  
  170.  
  171. (define (get-stack-register node)
  172.   (or (really-get-register node *first-stack-register* *real-registers* nil)
  173.       (really-get-register node P *first-stack-register* t)))
  174.  
  175. (define (get-stack-slot node)
  176.   (or (really-get-register node *first-stack-register* *real-registers* nil)
  177.       (really-get-temp node)))
  178.       
  179.  
  180.  
  181. (define (get-reg-if-free node)
  182.   (really-get-register node P *first-stack-register* nil))
  183.  
  184.  
  185. (define (really-get-register node start stop kick?)
  186.   (iterate loop ((i start))
  187.     (cond ((fx>= i stop)
  188.            (if kick? (select-and-kick-register node) nil))
  189.           ((not (reg-node i))
  190.        (or (fx< i *first-stack-register*)
  191.            (modify (lambda-max-temps *lambda*)
  192.                (lambda (max-temp)
  193.              (max 1 max-temp))))
  194.            i)
  195.           (else
  196.            (loop (fx+ i 1))))))
  197.  
  198. (define (into-register node value access)
  199.   (cond ((register-loc value))
  200.         (else         
  201.          (let ((reg (get-register node)))
  202.            (generate-move access reg)
  203.            (cond ((register-loc value)
  204.                   => (lambda (reg)
  205.                        (set (reg-node reg) nil))))
  206.            (mark value reg)
  207.            reg))))
  208.  
  209.  
  210. ;;; SELECT-AND-KICK-REGISTER The first register which is not locked or used soo
  211. ;;; is selected.  If none satisfy then the first register  is selected.
  212.                                           
  213. (define (select-and-kick-register node)
  214.          (iterate loop ((i A1) (default P)) ;kick P?
  215.            (cond ((fx>= i *real-registers*)
  216.                   (kick-register node default)
  217.                   default)
  218.                  ((locked? i) 
  219.                   (loop (fx+ i 1) default))
  220.                  ((not (used-soon? node (reg-node i)))
  221.                   (kick-register node i) 
  222.                   i)
  223.                  (else (loop (fx+ i 1) i)))))
  224.                                          
  225.  
  226. ;;; USED-SOON? Is this variable used at this node or at one of its
  227. ;;; continuations?
  228.  
  229. (define (used-soon? node value)                                        
  230.   (let ((var-used? (lambda (arg)
  231.                       (and (leaf-node? arg)
  232.                            (eq? (leaf-value arg) value)))))
  233.      (or (any? var-used? (call-args node))
  234.          (any? (lambda (cont)
  235.                  (any? var-used? (call-args (lambda-body cont))))
  236.                (continuations node)))))
  237.  
  238. (define-integrable (free-register node reg)
  239.   (if (reg-node reg) (kick-register node reg)))
  240.  
  241. (define (maybe-free reg cont)
  242.   (cond ((reg-node reg)
  243.          => (lambda (var)
  244.               (cond ((and (variable? var)
  245.                           (lambda-node? cont)
  246.                           (let ((spec (likely-next-reg var cont)))
  247.                             (cond ((and (fixnum? spec)
  248.                                         (not (reg-node spec)))
  249.                                    (generate-move reg spec)   
  250.                                    (set (reg-node reg) nil)
  251.                                    (set (register-loc var) nil)
  252.                                    (mark var spec)
  253.                                    t)
  254.                                   (else nil)))))
  255.                      (else nil))))
  256.          (else t)))
  257.  
  258.  
  259.  
  260. (define (kick-register node reg) 
  261.   (let ((value (reg-node reg)))
  262.     (cond ((locked? reg)
  263.            (error "attempt to kick out of locked register"))
  264.           ((or (temp-loc value)
  265.                (not (variable? value)))
  266.            (set (register-loc value) nil)
  267.            (set (reg-node reg) nil))
  268.           ((get-reg-if-free node)
  269.        => (lambda (temp)
  270.         (set (register-loc value) temp)
  271.         (set (reg-node reg) nil)
  272.         (set (reg-node temp) value)
  273.         (generate-move reg temp)))
  274.       (else
  275.            (let ((temp (get-stack-slot node)))
  276.              (set (register-loc value) nil)
  277.              (set (reg-node reg) nil)
  278.              (mark value temp)
  279.              (generate-move reg temp))))))
  280.  
  281.  
  282.  
  283. (define (really-get-temp node)
  284.   (cond ((really-get-register  node *real-registers* *virtual-registers* nil)
  285.          => (lambda (temp)
  286.           (modify (lambda-max-temps *lambda*)
  287.               (lambda (max-temp)
  288.             (max temp max-temp)))
  289.               temp))
  290.         (else
  291.          (bug "all temps used"))))
  292.      
  293.  
  294. (define-integrable (cont node)
  295.   (car (call-args node)))
  296.              
  297. (define (continuations node)               
  298.   (iterate loop ((i (call-exits node)) (args '()))
  299.     (cond ((fx= i 0) args)
  300.           (else
  301.            (let ((arg ((call-arg i) node)))
  302.              (loop (fx- i 1)
  303.                    (cond ((lambda-node? arg) (cons arg args))
  304.                          ((variable-known (leaf-value arg))
  305.                           => (lambda (label) (cons label args)))
  306.                          (else args))))))))
  307.  
  308. (define-integrable (then-cont node)
  309.   (car (call-args node)))
  310.  
  311. (define-integrable (else-cont node)
  312.   (cadr (call-args node)))
  313.  
  314. (define-integrable (kill-if-dying var node)
  315.   (if (dying? var node) (kill var)))
  316.  
  317.  
  318. (define (kill-if-dead node where)
  319.   (cond ((lambda-node? node)
  320.          (walk (lambda (var)
  321.                  (if (not (or (memq? var (lambda-live where))
  322.                               (fx= (variable-number var) 0)))
  323.                      (kill var)))
  324.                (lambda-live node)))
  325.         ((or (not (variable? (leaf-value node)))
  326.              (not (memq? (leaf-value node) (lambda-live where))))
  327.          (kill (leaf-value node)))))
  328.  
  329. (define (kill value)
  330.     (cond ((register-loc value)
  331.            => (lambda (reg)
  332.                 (cond ((locked? reg)
  333.                        (if (neq? (cdr (reg-node reg)) value)
  334.                            (bug "horrible inconsistancy reg ~S value ~S"
  335.                                  reg
  336.                                  value))
  337.                        (set (cdr (reg-node reg)) nil))
  338.                       (else
  339.                        (if (neq? (reg-node reg) value)
  340.                            (bug "horrible inconsistancy reg ~S value ~S"
  341.                                  reg
  342.                                  value))
  343.                        (set (reg-node reg) nil)))
  344.                  (set (register-loc value) nil))))
  345.     (cond ((temp-loc value)
  346.            => (lambda (reg)
  347.                 (cond ((locked? reg)
  348.                        (if (neq? (cdr (temp-node reg)) value)
  349.                            (bug "horrible inconsistancy reg ~S value ~S"
  350.                                  reg
  351.                                  value))
  352.                        (set (cdr (temp-node reg)) nil))
  353.                       (else
  354.                        (if (neq? (temp-node reg) value)
  355.                            (bug "horrible inconsistancy reg ~S value ~S"
  356.                                  reg
  357.                                  value))
  358.                        (set (temp-node reg) nil)))
  359.                  (set (temp-loc value) nil)))))
  360.  
  361. (define (live? value node)                    
  362.   (let ((value (cond ((and (pair? value) (variable? (cdr value)))
  363.                       (cdr value))
  364.                      ((variable? value) value)
  365.                      (else nil))))
  366.      (cond ((not value) nil)
  367.        ((eq? value (lambda-self-var *lambda*)) t)
  368.            (else 
  369.             (any? (lambda (cont)
  370.                      (memq? value (lambda-live cont)))
  371.                   (continuations node))))))
  372.  
  373. (define-integrable (dying? value node)
  374.   (not (live? value node)))
  375.  
  376. (define (dead? value node)
  377.   (let ((parent (node-parent node)))
  378.     (not (and (variable? value)
  379.               (or (memq? value (lambda-variables parent))
  380.                   (memq? value (lambda-live parent)))))))
  381.  
  382. ;;; pools for vector of registers (see ALLOCATE-CONDITIONAL-PRIMOP in reg.t)
  383.  
  384. (define register-vector-pool 
  385.         (make-pool 'reg-vec-pool 
  386.                    (lambda () (make-vector *virtual-registers*))
  387.                    15
  388.                    vector?))
  389.  
  390. (define-integrable (copy-registers)
  391.   (vector-replace (obtain-from-pool register-vector-pool)
  392.                   *registers*
  393.                   *virtual-registers*))
  394.                            
  395. (define-integrable (return-registers)
  396.   (return-to-pool register-vector-pool *registers*))
  397.  
  398. (define (restore-slots)
  399.     (restore-registers)
  400.     (restore-temps))
  401.  
  402. (define (restore-registers)
  403.   (do ((i 0 (fx+ i 1)))
  404.       ((fx>= i *real-registers* ))
  405.     (cond ((reg-node i)
  406.            (set (register-loc (reg-node i)) i)))))
  407.  
  408. (define (restore-temps)
  409.   (do ((i *real-registers* (fx+ i 1)))
  410.       ((fx>= i *virtual-registers*))
  411.     (cond ((temp-node i)
  412.            (set (temp-loc (temp-node i)) i)))))
  413.  
  414.  
  415.  
  416. (define (clear-slots)
  417.   (vector-fill *registers* nil)
  418.   (recycle *locations*)
  419.   (set *locations* (make-table 'locations)))
  420.          
  421. (define *lock-mark* (object nil ((identification self) 'lock)))
  422.  
  423.  
  424. (define-integrable (lock reg)
  425.   (and (fx>= reg 0)
  426.        (fx< reg *virtual-registers*)
  427.        (modify (reg-node reg) (lambda (node) (cons *lock-mark* node)))))
  428.  
  429. (define-integrable (unlock reg)
  430.   (and (fx>= reg 0)
  431.        (fx< reg *virtual-registers*)
  432.        (modify (reg-node reg) cdr)))
  433.  
  434. (define-integrable (locked? reg)
  435.   (let ((n (reg-node reg)))
  436.     (and (pair? n) (eq? (car n) *lock-mark*))))
  437.  
  438. (define (protect-access access)
  439.   (cond ((fixnum? access)
  440.      (lock access))
  441.         ((register? (car access)) 
  442.      (lock (car access)))))
  443.          
  444. (define (release-access access)
  445.   (cond ((fixnum? access)
  446.      (unlock access))
  447.         ((register? (car access)) 
  448.      (unlock (car access)))))
  449.               
  450. (define (mark value reg)
  451.   (cond ((register? reg)
  452.      (set (reg-node reg) value)
  453.      (set (register-loc value) reg))
  454.     (else
  455.      (set (temp-node reg) value)
  456.      (set (temp-loc value) reg))))
  457.          
  458.  
  459. ;;; Locations
  460. ;;;==========================================================================
  461. ;;;   Keeps track of where values are.
  462. ;;; A table of a-lists of form ((<type-of-location> . <index>)...) indexed by
  463. ;;; leaf values, i.e. variables, primops, or literals.
  464.  
  465. (lset *locations* (make-table 'locations))
  466.  
  467. (define-integrable (leaf-locations value)
  468.    (table-entry *locations* value))
  469.  
  470. (define-integrable register-loc
  471.   (object (lambda (value)
  472.             (get-location value 'reg))
  473.     ((identification self) 'register-loc)
  474.     ((setter self)
  475.      (lambda (value reg)
  476.        (if (null? reg)
  477.            (clear-location value 'reg)
  478.            (set-location value 'reg reg))))))
  479.  
  480. (define-integrable temp-loc
  481.   (object (lambda (value)
  482.             (get-location value 'temp))
  483.     ((identification self) 'temp-loc)
  484.     ((setter self)
  485.      (lambda (value temp)
  486.        (if (null? temp)
  487.            (clear-location value 'temp)
  488.            (set-location value 'temp temp))))))
  489.  
  490. (define-integrable (get-location value type)
  491.   (cdr (assq type (leaf-locations value))))
  492.  
  493. (define (set-location value type number)
  494.   (let ((locs (leaf-locations value)))
  495.     (cond ((assq type locs)
  496.            => (lambda (pair)
  497.                 (set (cdr pair) number)))
  498.           (else
  499.            (set-table-entry *locations* value (cons (cons type number) locs))))))
  500.  
  501. (define (clear-location value type)
  502.   (let ((locs (leaf-locations value)))
  503.     (set-table-entry *locations* value
  504.          (del! (lambda (x y) (eq? x (car y))) type locs))
  505.     nil))
  506.